Skip to content

Conversation

radhakrishnatg
Copy link
Contributor

Summary/Motivation:

This PR adds new features to the price-taker class. This is WIP. This PR needs to be merged after merging #1579

Changes proposed in this PR:

  • Fix a bug: Capacity limit constraints, startup-shutdown constraints, etc. would not work for indexed operation blocks. This is fixed in this PR.
  • Added methods for retrieving all operational and design variable values as pd.DataFrame and dict, respectively.
  • Added a method for plotting operational profiles.
  • Added a method for plotting LMP histograms
  • Added a generalized storage model class. If an instance of StorageModel is found in the flowsheet instance, then linking constraints are now added automatically.
  • Added support for automatic construction of polynomial-type surrogates.

Legal Acknowledgement

By contributing to this software project, I agree to the following terms and conditions for my contribution:

  1. I agree my contributions are submitted under the license terms described in the LICENSE.txt file at the top level of this directory.
  2. I represent I am authorized to make the contributions and grant the license. If my employer has rights to intellectual property that includes these contributions, I represent that I have received permission to make contributions and grant the required license on behalf of that employer.

@radhakrishnatg radhakrishnatg marked this pull request as draft June 10, 2025 20:57
@radhakrishnatg radhakrishnatg self-assigned this Jun 10, 2025
if self.config.fixed_design_data is not None:
# The design is fixed, so all the desired quantities are defined as parameters
for param_name, param_value in self.config.fixed_design_data.items():
setattr(self, param_name, Param(initialize=param_value, mutable=True))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why you chose mutable Params over fixing Vars ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite sure which option is preferable. If we define a Var and fix it, it would allow the user to unfix it. If they do that, then the design variable would be unconstrained and it may lead to an unexpected behavior.
I feel that declaring it as a Param would prevent unfixing and it ensures that the design is always fixed. I can change it to fixing Var if that is the convention we are following everywhere.

Copy link

codecov bot commented Jul 23, 2025

Codecov Report

❌ Patch coverage is 20.57416% with 166 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.82%. Comparing base (c84a7fe) to head (230199f).

Files with missing lines Patch % Lines
...s/grid_integration/pricetaker/price_taker_model.py 13.55% 102 Missing ⚠️
...egration/pricetaker/design_and_operation_models.py 29.67% 61 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1633      +/-   ##
==========================================
- Coverage   77.01%   76.82%   -0.19%     
==========================================
  Files         395      395              
  Lines       63555    63754     +199     
  Branches    10365    10408      +43     
==========================================
+ Hits        48944    48977      +33     
- Misses      12171    12335     +164     
- Partials     2440     2442       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines +400 to +401
@declare_process_block_class("StorageModel")
class StorageModelData(ProcessBlockData):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason why we don't just have this in a separate file?

Comment on lines +474 to +491
def _add_upper_bound(var_name, bound):
if isinstance(bound, (Var, Expression)):
setattr(
self,
var_name + "ub_con",
Constraint(
expr=getattr(self, var_name) <= bound,
doc=f"Constrains the maximum value of {var_name}",
),
)

else:
getattr(self, var_name).setub(bound)

_add_upper_bound("charge_rate", self.config.max_charge_rate)
_add_upper_bound("discharge_rate", self.config.max_discharge_rate)
_add_upper_bound("final_holdup", self.config.max_holdup)
_add_upper_bound("initial_holdup", self.config.max_holdup)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, this _add_upper_bound function essentially provides the upper bound for a variable by adding a constraint (named m.charge_rate_ub_con in the case of charge_rate, for example) when a Var or Expression is provided.

However, when a float, int, etc., is used, this constraint would not be constructed and the upper bound of the Var would just be set directly.

While it seems like a trivial and subtle difference, it also seems less than ideal to allow variation in model structure like this (where one version includes upper bound constraints and another analogous version does not, simply based on input provided).

Is there a reason why we don't just (1) check whether instance is a Var or Expression, and if so, just do setub(pyo.value(bound)) ? The only potential issue that I can foresee with that is if an indexed Var or Expression is passed in, but haven't checked. Are there other reasons?

@adam-a-a adam-a-a marked this pull request as ready for review July 31, 2025 17:56
@ksbeattie ksbeattie added Priority:Normal Normal Priority Issue or PR WaterTAP labels Aug 7, 2025
@ksbeattie
Copy link
Member

@radhakrishnatg, @adam-a-a: Moving this to the Nov release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Priority:Normal Normal Priority Issue or PR WaterTAP
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants